struct Parser<'g> {
    input: &'g str,
}

impl <'g> Parser <'g> {
    pub fn from_str(input: &'g str) -> Parser {
        Parser{ input }
    }
    fn unparsed(&self) -> Option<&'g str> {
        if self.input.len() > 0 { Some(self.input) } else { None }
    }
    
    //need to be test 
    fn peek_char(&self) -> Option<char>{
        self.input.chars().next()
    }

    //need to be test
    fn next_char(&mut self)-> Option<char>{
        let ch = self.peek_char()?;
        self.input = &self.input[ch.len_utf8()..];
        Some(ch)
    }

    fn string(&mut self) -> Result<&'g str, i32> {
        let start = self.input;
        let mut count = 0;
        loop {
            match self.peek_char() {
                Some(ch) => {
                    match ch {
                        ',' | ']' | '}' => {
                            break; // exit the loop
                        }
                        _ => {
                            count += 1;
                            self.input = &self.input[1..];
                        }
                    }
                }//Some(ch)
                None => {
                    break; //exit the loop
                }
            }
        }
        if count > 0 {
            return Ok(&start[0..count]);
        }
        Err(-1)
    }

    //TODO: 
    //  found: -> Result::Ok(Some(&'g str))
    //  not-found: -> Result::Ok(None) not-found
    //  error -> Result::Err(-2)  format-error
    pub fn parse_find(&mut self, key: &str) -> Result<&'g str, i32> {
        let k = self.key()?; // Result(k Or Err(-1))
        if !self.separator().is_ok() {
            return Err(-1);
        }
        if k == key {
            return Ok(self.input)
        }

        match self.string() {
            Ok(v) {
                if v != "" {

                } else {
                    return Ok("");
                }
            },
            Err(_) {
                return Err(-1);
            }
        }
        Ok(self.input);
    }
    fn key(&mut self) -> Result<&'g str, i32>{
        if self.input.len() > 3 {
            let result = &self.input[0..3];
            self.input = &self.input[3..];
            //TODO: check the result[0..3]
            return Ok(result);
        } 
        Err(-1)
    }
    fn separator(&mut self) -> Result<&'g str, i32> {
        match self.next_char() {
            Some(ch) =>  { 
                if ch == '=' { Ok(self.input) } else { Err(-1) }
            },
            None =>  { Err(-1) }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_from_str(){
        let input = "X01=hello";
        let p = Parser::from_str(input);
        assert_eq!(Some(input), p.unparsed());
    }
    #[test]
    fn test_peek_char(){
        { //Some(x)
            let input = "X01=hello";
            let p = Parser::from_str(input);
            assert_eq!(Some('X'), p.peek_char());
            assert_eq!(Some(input), p.unparsed());
        }
        { //None
            let p = Parser::from_str("");
            assert_eq!(None, p.peek_char());
            assert!(p.unparsed().is_none());
        }
    }
    #[test]
    fn test_next_char(){
        { // Some(x)
            let input = "X01=hello";
            let mut p = Parser::from_str(input);
            assert_eq!(Some('X'), p.next_char());
            assert_eq!(Some(&input[1..]), p.unparsed());
        }
        { // Some(x) -> None
            let input = "X";
            let mut p = Parser::from_str(input);
            assert_eq!(Some(input), p.unparsed());

            assert_eq!(Some('X'), p.next_char());
            assert!(p.unparsed().is_none());
        }
    }
    #[test]
    fn test_key(){
        {
            let input = "X01=hello";
            let mut p = Parser::from_str(input);
            assert_eq!("X01", p.key().unwrap());
        }
        {
            let input = "X";
            let mut p = Parser::from_str(input);
            assert_eq!(Err(-1), p.key());
        }
    }
    #[test]
    fn test_string(){
        {
            let input = "hello";
            let mut p = Parser::from_str(input);
            assert_eq!("hello", p.string().unwrap());
        }
        {
            let input = "";
            let mut p = Parser::from_str(input);
            assert_eq!("", p.string().unwrap());
        }
        {
            let input = ",";
            let mut p = Parser::from_str(input);
            assert_eq!("", p.string().unwrap());
            assert_eq!(input, p.unparsed().unwrap());
        }
        {
            let input = "]";
            let mut p = Parser::from_str(input);
            assert_eq!("", p.string().unwrap());
            assert_eq!(input, p.unparsed().unwrap());
        }
        {
            let input = "}";
            let mut p = Parser::from_str(input);
            assert_eq!("", p.string().unwrap());
            assert_eq!(input, p.unparsed().unwrap());
        }
    }
    #[test]
    fn test_parse_find(){
        let input = "X01=hello";
        let mut p = Parser::from_str(input);
        match p.parse_find("X01") {
            Ok(v) => {
                assert_eq!("hello", v);
            },
            Err(_) => {
                assert!(false);
            },
        }
    }
}
